package plus;
/**
 * Not every named variable is accessible from every point in (e.g.) a subroutine,
 * and it's feasible that the same name may be reused in disjoint scopes tied to the same
 * implementation-dynamic-extent.
 * so this class is responsible for the visibility of variables by name
 * -- thus providing the find_variable(name) method -- 
 * but relies for their allocation on the stack (or in the BSS) on a DynamicExtent object.
 * @author me
 *
 */
public final class VScope {
	public static VScope current = null;
	public final DynamicExtent dynex;
	final VScope outer;
	private VScope(VScope outer, DynamicExtent dynex) {
		this.outer = outer;
		this.dynex = dynex;
	}
	public static VScope enterBlock() { current = new VScope(current, current.dynex); return current; }
	public static VScope enterProc(DynamicExtent dynex) { current = new VScope(current, dynex); return current; }
	public static void exit() { current = current.outer; }

	Scope<Variable> vars = new Scope<Variable>();
	
	public Symbol<Variable> find_variable(String name) {
		Symbol<Variable> v = vars.find(name);
		if (v != null) return v;
		if (outer != null) return outer.find_variable(name);
		return null;
	}
	public Symbol<Variable> add_local(String name, int lineNr) {
		return vars.enter(new Symbol<Variable>(name, lineNr, dynex.newLocal()));
	}
	public Symbol<Variable> add_local(String name, int lineNr, Type type) {
		return vars.enter(new Symbol<Variable>(name, lineNr, dynex.newLocal(type)));
	}
	public Symbol<Variable> add_param(String name, int lineNr, Type type) {
		return vars.enter(new Symbol<Variable>(name, lineNr, dynex.newParam(type)));
	}
}
